// requestQueue.ts
import { ref, reactive, onUnmounted, getCurrentInstance } from 'vue';

// 基础配置
const baseConfig = {
	get baseURL() {
		const ipAgreement = uni.getStorageSync("IPAgreement") || "";
		const serverIP = uni.getStorageSync("serverIP") || "";
		return ipAgreement + serverIP;
	},
	maxRetry: 1, // 默认重试次数
	retryDelay: 1000, // 重试延迟(ms)
	unwrapData: false, // 是否自动剥离data层
	apiPrefix: '/Frame/SqlData?cmdname=' // 新增：默认接口前缀
};

// 请求任务接口
interface RequestTask {
	id : string;
	url : string;
	method : 'GET' | 'POST' | 'PUT' | 'DELETE';
	data ?: any;
	config : RequestConfig;
	resolve : (value : any) => void;
	reject : (reason ?: any) => void;
	retryCount : number;
}

// 请求配置接口（新增apiPrefix字段）
interface RequestConfig {
	baseURL ?: string;
	maxRetry ?: number;
	retryDelay ?: number;
	headers ?: RequestHeaders;
	isFullUrl ?: boolean; // 是否为完整URL
	onSuccess ?: (response : any) => void;
	onError ?: (error : any) => void;
	unwrapData ?: boolean; // 是否剥离data层
	apiPrefix ?: string; // 新增：接口地址前缀
	[key : string] : any;
}

// 请求头接口
interface RequestHeaders {
	[key : string] : string;
}

// 错误类型
enum ErrorType {
	NETWORK_ERROR = 'NETWORK_ERROR',
	TIMEOUT = 'TIMEOUT',
	SERVER_ERROR = 'SERVER_ERROR',
	CLIENT_ERROR = 'CLIENT_ERROR',
}

// 对象深度合并函数
function deepMerge(target : any, source : any) : any {
	const isObject = (obj : any) => obj && typeof obj === 'object';

	if (!isObject(target) || !isObject(source)) {
		return source;
	}

	Object.keys(source).forEach(key => {
		const targetValue = target[key];
		const sourceValue = source[key];

		if (Array.isArray(targetValue) && Array.isArray(sourceValue)) {
			target[key] = sourceValue; // 数组直接替换
		} else if (isObject(targetValue) && isObject(sourceValue)) {
			target[key] = deepMerge(targetValue, sourceValue); // 递归合并对象
		} else {
			target[key] = sourceValue; // 基本类型直接替换
		}
	});

	return target;
}

// 获取默认请求头
function getDefaultHeaders() : RequestHeaders {
	const headers : RequestHeaders = {
		'content-type': 'application/x-www-form-urlencoded;charset=utf-8',
		// 'Content-Type': 'application/json',
		// 'Accept': 'application/json'
	};

	// 动态添加username（如果存在）
	const userInfo = uni.getStorageSync('UserInfo');
	if (userInfo) {
		headers['username'] = encodeURIComponent(JSON.parse(userInfo).UserName);
	}

	return headers;
}

// 请求队列管理器
class RequestQueueManager {
	private queue : RequestTask[] = [];
	private runningTasks : Map<string, RequestTask> = new Map();
	private maxConcurrent = 5; // 最大并发数
	private instanceId = '';
	private isDestroyed = false;

	// 统计信息
	private stats = reactive({
		total: 0,
		completed: 0,
		failed: 0,
		pending: 0
	});

	// 事件监听
	private listeners = {
		complete: [] as ((stats : typeof this.stats) => void)[],
		error: [] as ((error : any) => void)[]
	};

	constructor(instanceId : string) {
		this.instanceId = instanceId;
	}

	// 添加请求到队列
	addRequest(task : RequestTask) {
		if (this.isDestroyed) return;

		this.queue.push(task);
		this.stats.total++;
		this.stats.pending++;
		this.runNext();
	}

	// 运行下一个任务
	private runNext() {
		if (this.isDestroyed) return;

		if (this.runningTasks.size >= this.maxConcurrent || this.queue.length === 0) {
			return;
		}

		const task = this.queue.shift()!;
		this.stats.pending--;
		this.runningTasks.set(task.id, task);

		this.executeRequest(task);
	}

	// 执行请求（修改URL拼接逻辑）
	private async executeRequest(task : RequestTask) {
		if (this.isDestroyed) return;

		// 合并默认头和用户头，用户头优先
		const headers = deepMerge(
			{ ...getDefaultHeaders() },
			{ ...task.config.headers }
		) as RequestHeaders;

		const { url, method, data, config } = task;
		// 获取接口前缀（配置优先，默认次之）
		const apiPrefix = config.apiPrefix ?? baseConfig.apiPrefix;
		// 核心修改：判断是否使用配置的baseURL
		const useConfigBaseURL = typeof config.baseURL !== 'undefined';
		// 拼接完整URL：配置了baseURL则直接拼接，否则使用默认baseURL+apiPrefix+url
		const fullUrl = config.isFullUrl
			? url
			: useConfigBaseURL
				? `${config.baseURL}${url}`
				: `${baseConfig.baseURL}${apiPrefix}${url}`;

		if (uni.getStorageSync('UserInfo')) {
			let UserInfo = JSON.parse(uni.getStorageSync('UserInfo'))

			if (!data?.hasOwnProperty("P_UserID")) {
				data.P_UserID = UserInfo.UserID;
			}
			if (!data?.hasOwnProperty("P_UserName")) {
				data.P_UserName = UserInfo.UserName;
			}
			if (!data?.hasOwnProperty("P_UserCode")) {
				data.P_UserCode = UserInfo.UserCode;
			}
			if (!data?.hasOwnProperty("P_EmplID")) {
				data.P_EmplID = UserInfo.EmplID;
			}
		}
		try {
			const response = await uni.request({
				url: fullUrl,
				method,
				data,
				header: headers,
				timeout: config.timeout || 30000
			});
			

			// 处理响应数据
			const processedResponse = this.processResponse(response, config);
			// console.log(processedResponse);

			this.handleSuccess(task, processedResponse);
		} catch (error) {
			this.handleError(task, error);
		}
	}

	// 处理响应数据
	private processResponse(response : any, config : RequestConfig) {
		// 默认剥离最外层data
		const shouldUnwrap = config.unwrapData ?? baseConfig.unwrapData;

		// 如果配置了unwrapData为true，并且响应格式符合预期，则只剥离最外层的data
		if (shouldUnwrap &&
			response &&
			response.data &&  // 确保响应有data属性
			typeof response.data === 'object' &&
			response.data !== null &&
			'data' in response.data) {  // 确保最外层有data字段

			// 只返回最外层data字段的值（保留内部结构）
			return response.data.data;
		}

		// 否则返回原始响应
		return response.data || response;
	}

	// 处理成功响应
	private handleSuccess(task : RequestTask, response : any) {
		if (this.isDestroyed) return;

		this.runningTasks.delete(task.id);
		this.stats.completed++;

		task.resolve(response);
		task.config.onSuccess?.(response);

		// 检查是否所有请求都已完成
		this.checkCompletion();

		// 继续处理下一个任务
		this.runNext();
	}

	// 处理错误
	private handleError(task : RequestTask, error : any) {
		if (this.isDestroyed) return;

		const maxRetry = task.config.maxRetry ?? baseConfig.maxRetry;

		if (task.retryCount < maxRetry) {
			task.retryCount++;

			// 重试延迟
			setTimeout(() => {
				if (this.isDestroyed) return;

				this.queue.unshift(task);
				this.stats.pending++;
				this.runNext();
			}, task.config.retryDelay ?? baseConfig.retryDelay);

			return;
		}

		// 重试次数用尽
		this.runningTasks.delete(task.id);
		this.stats.failed++;

		const errorInfo = {
			error,
			task,
			type: this.getErrorType(error)
		};

		task.reject(errorInfo);
		task.config.onError?.(errorInfo);
		this.listeners.error.forEach(listener => listener(errorInfo));

		// 检查是否所有请求都已完成
		this.checkCompletion();

		// 继续处理下一个任务
		this.runNext();
	}

	// 获取错误类型
	private getErrorType(error : any) : ErrorType {
		if (error.errMsg.includes('timeout')) return ErrorType.TIMEOUT;
		if (error.errMsg.includes('network')) return ErrorType.NETWORK_ERROR;
		if (error.statusCode >= 500) return ErrorType.SERVER_ERROR;
		if (error.statusCode >= 400) return ErrorType.CLIENT_ERROR;

		return ErrorType.NETWORK_ERROR;
	}

	// 检查是否所有请求都已完成
	private checkCompletion() {
		if (this.runningTasks.size === 0 && this.queue.length === 0) {
			this.listeners.complete.forEach(listener => listener(this.stats));
		}
	}

	// 注册完成监听
	onComplete(callback : (stats : typeof this.stats) => void) {
		this.listeners.complete.push(callback);
		return () => {
			const index = this.listeners.complete.indexOf(callback);
			if (index !== -1) this.listeners.complete.splice(index, 1);
		};
	}

	// 注册错误监听
	onError(callback : (error : any) => void) {
		this.listeners.error.push(callback);
		return () => {
			const index = this.listeners.error.indexOf(callback);
			if (index !== -1) this.listeners.error.splice(index, 1);
		};
	}

	// 销毁队列
	destroy() {
		this.isDestroyed = true;
		this.queue = [];
		this.runningTasks.clear();
		this.listeners.complete = [];
		this.listeners.error = [];
	}
}

// 生成唯一ID
function generateId() {
	return Math.random().toString(36).substr(2, 9);
}

// 请求实例映射
const requestInstances = new Map();

// 获取当前页面的请求队列
function useRequestQueue() {
	const instance = getCurrentInstance();
	if (!instance) throw new Error('请在Vue组件中使用useRequestQueue');

	const instanceId = instance.uid.toString();

	// 创建或获取请求队列实例
	let requestQueue = requestInstances.get(instanceId);
	if (!requestQueue) {
		requestQueue = new RequestQueueManager(instanceId);
		requestInstances.set(instanceId, requestQueue);
	}

	// 组件销毁时清理
	onUnmounted(() => {
		requestQueue?.destroy();
		requestInstances.delete(instanceId);
	});

	// 统一请求方法 - 支持回调
	const request = <T = any>(options : {
		url : string;
		method : 'GET' | 'POST' | 'PUT' | 'DELETE';
		data ?: any;
		config ?: RequestConfig;
		success ?: (response : T) => void;
		fail ?: (error : any) => void;
	}) => {
		return new Promise<T>((resolve, reject) => {
			const task : RequestTask = {
				id: generateId(),
				url: options.url,
				method: options.method,
				data: options.data,
				config: {
					// ...baseConfig,
					...options.config
				},
				resolve: (response) => {
					options.success?.(response as T);
					resolve(response as T);
				},
				reject: (error) => {
					options.fail?.(error);
					reject(error);
				},
				retryCount: 0
			};

			requestQueue!.addRequest(task);
		});
	};

	// requestByUrl方法 - 支持回调
	const requestByUrl = <T = any>(options : {
		url : string;
		method : 'GET' | 'POST' | 'PUT' | 'DELETE';
		data ?: any;
		config ?: RequestConfig;
		success ?: (response : T) => void;
		fail ?: (error : any) => void;
	}) => {
		return new Promise<T>((resolve, reject) => {
			// 获取配置中的baseURL
			let baseURL = options.config?.baseURL || '';

			// console.log(baseURL);
			// 处理baseURL
			if (!baseURL.includes('http') && !baseURL.includes('https')) {
				// 获取存储的IP地址
				const serverIP = uni.getStorageSync('serverIP') || '';
				// console.log(serverIP);
				const IPAgreement = uni.getStorageSync("IPAgreement") || "http://"
				// 拼接完整URL
				baseURL = `${IPAgreement}${serverIP}${baseURL}`;
			}
			// console.log(baseURL);
			const task : RequestTask = {
				id: generateId(),
				url: options.url,
				method: options.method,
				data: options.data,
				config: {
					// ...baseConfig,
					...options.config,
					baseURL
				},
				resolve: (response) => {
					options.success?.(response as T);
					resolve(response as T);
				},
				reject: (error) => {
					options.fail?.(error);
					reject(error);
				},
				retryCount: 0
			};

			requestQueue!.addRequest(task);
		});
	};

	// Promise风格请求方法
	const PromiseRequest = <T = any>(options : {
		url : string;
		method : 'GET' | 'POST' | 'PUT' | 'DELETE';
		data ?: any;
		config ?: RequestConfig;
	}) : Promise<T> => {
		return new Promise((resolve, reject) => {
			const task : RequestTask = {
				id: generateId(),
				url: options.url,
				method: options.method,
				data: options.data,
				config: {
					// ...baseConfig,
					...options.config
				},
				resolve,
				reject,
				retryCount: 0
			};

			requestQueue!.addRequest(task);
		});
	};

	// Promise风格requestByUrl方法
	const PromiseRequestByUrl = <T = any>(options : {
		url : string;
		method : 'GET' | 'POST' | 'PUT' | 'DELETE';
		data ?: any;
		config ?: RequestConfig;
	}) : Promise<T> => {
		return new Promise((resolve, reject) => {
			// 获取配置中的baseURL
			let baseURL = options.config?.baseURL || '';

			// 处理baseURL
			if (!baseURL.includes('http') && !baseURL.includes('https')) {
				// 获取存储的IP地址
				const serverIP = uni.getStorageSync('serverIP') || '';

				const IPAgreement = uni.getStorageSync("IPAgreement") || "http://"
				// 拼接完整URL
				baseURL = `${IPAgreement}${serverIP}${baseURL}`;
			}

			const task : RequestTask = {
				id: generateId(),
				url: options.url,
				method: options.method,
				data: options.data,
				config: {
					// ...baseConfig,
					...options.config,
					baseURL
				},
				resolve,
				reject,
				retryCount: 0
			};

			requestQueue!.addRequest(task);
		});
	};

	return {
		request,
		requestByUrl,
		PromiseRequest,
		PromiseRequestByUrl,
		onComplete: requestQueue.onComplete.bind(requestQueue),
		onError: requestQueue.onError.bind(requestQueue),
		stats: requestQueue.stats
	};
}

export default useRequestQueue;